#include <Theron/Theron.h> 

#if 0

template <class WorkMessage>
class Worker : public Theron::Actor
{
public:

	// Constructor. 
	Worker(Theron::Framework &framework) : Theron::Actor(framework)
	{
		RegisterHandler(this, &Worker::Handler);
	}

private:

	// Message handler for WorkMessage messages. 
	void Handler(const WorkMessage &message, const Theron::Address from)
	{
		// The message parameter is const so we need to copy it to change it.
		WorkMessage result(message);
		result.Process();

		// Forward the processed message back to the sender. 
		Send(result, from);
	}
};

// A file read request: read the contents of a disk file into a memory buffer.
struct ReadRequest
{
public:

	explicit ReadRequest(
		const Theron::Address client = Theron::Address(),
		const char *const fileName = 0,
		unsigned char *const buffer = 0,
		const unsigned int bufferSize = 0) :
		mClient(client),
		mFileName(fileName),
		mProcessed(false),
		mBuffer(buffer),
		mBufferSize(bufferSize),
		mFileSize(0)
	{
	}

	void Process()
	{
		mProcessed = true;
		mFileSize = 0;

		// Try to open the file. 
		FILE *const handle = fopen(mFileName, "rb");
		if (handle != 0)
		{
			// Read the file data, setting the actual size. 
			mFileSize = (uint32_t)fread(
				mBuffer,
				sizeof(unsigned char),
				mBufferSize,
				handle);

			fclose(handle);
		}
	}

	Theron::Address mClient;            // Address of the requesting client.
	const char *mFileName;              // Name of the requested file. 
	bool mProcessed;                    // Whether the file has been read.
	unsigned char *mBuffer;             // Buffer for file contents. 
	unsigned int mBufferSize;           // Size of the buffer. 
	unsigned int mFileSize;             // Size of the file in bytes. 
};

static const int MAX_FILES = 16;
static const int MAX_FILE_SIZE = 16384;

int main(int argc, char *argv[])
{
	if (argc < 2)
	{
		printf("Expected up to 16 file name arguments.\n");
	}

	// Create a worker to process the work. 
	Theron::Framework framework;
	Worker<ReadRequest> worker(framework);

	// Register a handler with a receiver to catch the result messages. 
	Theron::Receiver receiver;
	Theron::Catcher<ReadRequest> resultCatcher;
	receiver.RegisterHandler(&resultCatcher, &Theron::Catcher<ReadRequest>::Push);

	// Send the work requests, one for each file name on the command line.
	for (int i = 0; i < MAX_FILES && i + 1 < argc; ++i)
	{
		unsigned char *const buffer = new unsigned char[MAX_FILE_SIZE];
		const ReadRequest message(
			receiver.GetAddress(),
			argv[i + 1],
			buffer,
			MAX_FILE_SIZE);

		framework.Send(message, receiver.GetAddress(), worker.GetAddress());
	}

	// Wait for all results. 
	for (int i = 1; i < argc; ++i)
	{
		receiver.Wait();
	}

	// Handle the results; we just print the sizes of the files. 
	ReadRequest result;
	Theron::Address from;
	while (!resultCatcher.Empty())
	{
		resultCatcher.Pop(result, from);
		printf("Read %d bytes from file '%s'\n", result.mFileSize, result.mFileName);

		// Free the allocated buffer. 
		delete[] result.mBuffer;
	}
}

#endif
